/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  TableCodecCommon.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/09/11
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#ifndef TABLECODECCOMMON_H_FEA9060A_0A17_4D17_852F_14E0B38AADEA
#define TABLECODECCOMMON_H_FEA9060A_0A17_4D17_852F_14E0B38AADEA
#include <vector>
#include <map>
#include "../extdef.h"


namespace qb{
	namespace proto{


#define 	kOpTypeNew		0x00	// 全新值
#define 	kOpTypeDefault	0x01	// 默认值
#define 	kOpTypeCopy		0x02	// 与前一个值相同
#define 	kOpTypeDelta	0x03	// 相对前一个值的变化量
#define     OpBitWidth      2       // opbit宽度为2,总共有4个编码为

		enum kExpectType{
			kExpectTypeNull,		// 默认值
			kExpectTypeString,		// 字符串
			kExpectTypeDouble,		// 双精度浮点数
			kExpectTypeInt,			// 整数:变长无符号64位整数
			kExpectTypeMax
		};
		inline bool IsIntegerType(kExpectType type){
			return type == kExpectTypeInt;
		}
		inline bool IsNumberType(kExpectType type){
			return type == kExpectTypeDouble || IsIntegerType(type);
		}

#define	ShiftDigit		7				//移动位数
#define TypeBitCount	4
#define EncodeTypeMask  ((1<<TypeBitCount)-1)		// 低4位
		enum kEncodeType{				// 这里最多支持32种,因为EncodeTypeMask只有5个bit可用
			kEncodeTypeStrRaw = 0,		// gbk;		// 编码, 支持中文
			kEncodeTypeStrAlpNum = 1,	// [a-zA-Z0-9\.\-]字母和数字
			kEncodeTypeStrNum = 2,		// [0-9\.\-] + , 数字格式, 可以是浮点数
			kEncodeTypeVarInt = 3,		// 每个字段都是整数, 可变长
			kEncodeTypeVarUint= 4,		// 变长无符号整数,只针对正整数
			kEncodeTypeDouble=5,		// 浮点数
			kEncodeTypeAuto = 6,		//	自动编码类型,特殊类型
			kEncodeTypeFixedBit = 7,	// 每个字段都占用固定个bit, 需要后续指定bit的长度
			kEncodeTypeList = 8,		// List
			kEncodeTypeMap = 9,			// Map
			kEncodeTypeTable = 10,		// Table
			kEncodeTypeBinary=11,		// 二进制
			kEncodeTypeMax = 1 << TypeBitCount			// 最大编码类型,所有编码类型必须小于此值
		};

		enum kNameType{
			kNameTypeString			=0,		// 列名称是字符串
			kNameTypeIntScatter		=1,		// 列名称是数字,且无序
			kNameTypeIntSortted		=2,		// 列名称是排好序的
			kNameTypeIntIncrement	=3,		// 列名称是严格递增的,递增值为1
			kNameTypeIntMultiIncrement = 4,	// 多个等差数列
		};
		struct IncArray{		// 等差数列
			int		m_base;		// 基数
			int		m_delta;	// 递增值
			int		m_count;	// 个数
		public:
			IncArray() :m_base(0), m_delta(0), m_count(0){}
			IncArray(int base) :m_base(base), m_delta(0), m_count(1){}
			IncArray(int base, int delta, int count) :m_base(base), m_delta(delta), m_count(count){}
			inline void reset(int base){ m_base = base; m_delta = 0; m_count = 1; }
			inline int	count()const{ return m_count; }
			inline int  base()const{ return m_base; }
			inline int delta()const{ return m_delta; }
			bool add(int num);
		};

#define TableFlagHasZipped		(1<<4)	// 后续内容是否压缩过
#define TableFlagHasFieldNames	(1<<5)	// 是否有字段名称
#define TableFlagHasDict		(1<<6)	// 是否有字典


#define FieldFlagHasDictIndex	(1<<5)	// 0x20	如果为dict,那么指定dict的条数,如果为字段,那么为字段的字典编号
#define FieldFlagHasOpBitmap	(1<<6)	// 
#define FieldFlagHasConvert		(1<<7)	// 原先是string,编码成int存储
#define FieldFlagHasDefault		(1<<7)	//
#define FieldFlagHasGroup		(1<<5)	// 多个列的数据存储在一个数组中,交错



#define DefaultValueFlag (1<<4)			// 0-3共4位用于表示类型,第4位表示是否有默认值
#define StatusEnd		(1<<7)			// 结束标识
#define CompleteFlag	(1<<6)			// 完整标志
		/*///////////////////////////////////////////////////////////////////////////////
		table =
		(Int row 	该table包含多少条记录)
		(Int col 	该table包含多少个字段)
		(Int ndict 	该table包含的字典个数)
		(? dict 	如果ndict > 0, 那么字典存在, 如果ndict <= 0, 那么字段编码不存在)
		(? coldata 	列数据的编码, 参见coldata的定义)

		coldata =
		(Int type 	6bit表示opbitmap是否存在, 5bit表示dictid是否存在, 4 - 0组合表示kCodeType值)
		(? opbitmap 	变长, 每2bit表示一个字段的op信息, 共有4中op编码, 如果是copy则该字段跳过)
		(Int dictid ? 如果ndict > 0, 此数据存在, 表示dict数组中第几个字典信息, 此时, 此列类型应该是Int或者Bit)
		(Int bitwidth 	如果type是kCodeTypeBit, 表示每个字段占据bitwidth个bit位)
		(v0, v1, v2, v3, ...vn - 1  	该列所有数据, 如果对应的op为copy则跳过)

		dict = coldata

		opbitmap =
		(Bit v0, v1, v2, v3, ...	bitwidth为2, 表示每个字段对应的op值, 可选为4个, 默认是new, 如果是copy, 则coldata中对应的字段值跳过

		///////////////////////////////////////////////////////////////////////////////*/
		struct StringPtr{
			char*	ptr;			// 由TableCodec分配,里面无需管理释放,编解码结束后统一释放
			int			len;
		};
		typedef unsigned int u32;
		typedef long long i64;
		typedef unsigned long long ui64;
		class TableCodec;
		class SSPROTOAPI ConvertPrecision{
		public:

			// 获取精度为width位小数的阈值
			static double GetThreadhold(int width=6);

			// 获取精度为width位小数的格式
			static const char* GetFormat(int width=6);
		};
		//static_assert(sizeof(double) == sizeof(ui64), "sizeof(double) must equal to sizeof(ui64)");
		struct SSPROTOAPI VarValue{
			kExpectType	type;
			union
			{
				double			d;
				i64				i;
				ui64			u;
				StringPtr	  str;
			};
			VarValue();
			VarValue(double n) :type(kExpectTypeDouble), d(n){}
			VarValue(i64 n) :type(kExpectTypeInt), i(n){}
			VarValue(int n) :type(kExpectTypeInt), i(n){}
			VarValue(unsigned int n) :type(kExpectTypeInt), i(n){}
			VarValue(ui64 n) :type(kExpectTypeInt), i(n){}
			VarValue(const char* s, int len) :type(kExpectTypeString){ str.ptr = const_cast<char *>(s); str.len = len; }//强转，需要注意

			void AddDelta(const VarValue& delta,TableCodec* allocator);
			VarValue Delta(const VarValue& last, TableCodec* allocator)const;
			bool EqualWith(const VarValue& vv)const;
			bool IsDefault()const;

			unsigned char GetStringOp(const VarValue& last, kEncodeType encodetype, int& size)const;

		};
	}//namespace base;
}//namespace ss;



#endif


